home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 December: Technology Seed / ATS Dec. '97.toast / Navigation Services SDK 1.0b1 / Examples / Sampler / Sampler ƒ / file.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-20  |  22.8 KB  |  892 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        file.c
  3.  
  4.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. #pragma segment DocSeg
  9.  
  10. #ifndef __STRINGS__
  11. #include <Strings.h>
  12. #endif
  13.  
  14. #ifndef __STDIO__
  15. #include <StdIO.h>
  16. #endif
  17.  
  18. #ifndef __STANDARDFILE__
  19. #include <StandardFile.h>
  20. #endif
  21.  
  22. #ifndef __FINDER__
  23. #include <Finder.h>
  24. #endif
  25.  
  26. #ifndef __NAVIGATION__
  27. #include "Navigation.h"
  28. #endif
  29.  
  30. #ifndef Common_Defs
  31. #include "Common.h"
  32. #endif
  33.  
  34. const long kPictHeaderSize = 512;
  35.  
  36. short ReadFile(Document* theDocument);
  37. short WriteFile(Document* theDocument);
  38. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec);
  39. short DoSaveAsDocument(Document* theDocument);
  40. short DoSaveAsDocumentOldWay(Document* theDocument);
  41.  
  42. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode);
  43.  
  44. extern Document* gDocumentList[kMaxDocumentCount];
  45. extern Boolean gNavServicesExists;
  46.  
  47.  
  48. // *****************************************************************************
  49. // *
  50. // *    ReadFile()
  51. // *
  52. // *****************************************************************************
  53. short ReadFile(Document* theDocument)
  54. {    
  55.     long        count;
  56.     short        theResult;
  57.     char        buffer[256];
  58.     TextStyle    theStyle;
  59.  
  60.     SetCursor(*GetCursor(watchCursor));
  61.  
  62.     if (theDocument->theTE != NULL)
  63.         {
  64.         TESetSelect(0,(**(theDocument->theTE)).teLength,theDocument->theTE);
  65.         TEDelete(theDocument->theTE);
  66.  
  67.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  68.             return theResult;
  69.  
  70.         do    {
  71.             count = 256;
  72.             theResult = FSRead(theDocument->fRefNum,&count,&buffer);
  73.             TEInsert(&buffer,count,theDocument->theTE);
  74.             }
  75.         while (theResult == noErr);
  76.  
  77.         if (theResult == eofErr)
  78.             theResult = noErr;
  79.     
  80.         TESetSelect(0,32767,theDocument->theTE);
  81.         theStyle.tsFont = 21;
  82.         theStyle.tsSize = 12;
  83.         TESetStyle(doFont + doSize,&theStyle,true,theDocument->theTE);
  84.         TESetSelect(0,0,theDocument->theTE);
  85.         }
  86.     else
  87.         {
  88.         short     result = noErr;
  89.         long    fileSize = 0;
  90.         long    headerSize = 0;
  91.         long    pictSize = 0;
  92.  
  93.         SetCursor(*(Cursor**)GetCursor(watchCursor));
  94.         
  95.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  96.             return theResult;
  97.  
  98.         theResult = GetEOF(theDocument->fRefNum,&fileSize);
  99.         
  100.         theDocument->fPictLength = fileSize;
  101.         theDocument->fPictLength -= kPictHeaderSize;
  102.         theDocument->fPict = NewHandle(theDocument->fPictLength);
  103.         theDocument->fHeader = NewHandle(kPictHeaderSize);
  104.         if ((theDocument->fPict == NULL)||(theDocument->fPict == NULL))
  105.             {
  106.             SysBeep(5);
  107.             return memFullErr;
  108.             }
  109.         headerSize = kPictHeaderSize;
  110.         pictSize = theDocument->fPictLength;
  111.  
  112.         theResult = FSRead(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  113.         theResult = FSRead(theDocument->fRefNum,&pictSize,*theDocument->fPict);
  114.         }
  115.  
  116.     theDocument->dirty = false;
  117.  
  118.     if (theResult != noErr)
  119.         {
  120.         Str255 errorStr;
  121.         GetIndString(errorStr,rAppStringsID,sReadErr);
  122.         ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  123.         NoteAlert(rGenericAlertID,0L);
  124.         }
  125.     return theResult;
  126. }
  127.  
  128.  
  129. // *****************************************************************************
  130. // *
  131. // *    WriteFile()
  132. // *
  133. // *****************************************************************************
  134. short WriteFile(Document* theDocument)
  135. {    
  136.     short    theResult;
  137.     long    length;
  138.     char*    bufPtr;
  139.  
  140.     SetCursor(*GetCursor(watchCursor));
  141.  
  142.     if (!theDocument->fRefNum)
  143.         return fnOpnErr;
  144.  
  145.     if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  146.         return theResult;
  147.  
  148.     if (theDocument->theTE != NULL)
  149.         {
  150.         length = (**(theDocument->theTE)).teLength;
  151.         bufPtr = *((**(theDocument->theTE)).hText);
  152.  
  153.         theResult = FSWrite(theDocument->fRefNum,&length,bufPtr);
  154.         if (theResult == noErr)
  155.             theResult = SetEOF(theDocument->fRefNum,length);
  156.         }
  157.     else
  158.         {
  159.         long headerSize = kPictHeaderSize;
  160.         long pictSize = theDocument->fPictLength;
  161.  
  162.         theResult = FSWrite(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  163.         if (theResult == noErr)
  164.             {
  165.             theResult = FSWrite(theDocument->fRefNum,&pictSize,*theDocument->fPict);    
  166.             if (theResult == noErr)
  167.                 theResult = SetEOF(theDocument->fRefNum,headerSize+pictSize);
  168.             }
  169.         }
  170.  
  171.     return theResult;
  172. }
  173.  
  174.  
  175. // *****************************************************************************
  176. // *
  177. // *    WriteNewFile()
  178. // *
  179. // *****************************************************************************
  180. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec)
  181. {    
  182.     short    theResult;
  183.     short    refNum = 0;
  184.  
  185.     SetCursor(*GetCursor(watchCursor));
  186.  
  187.     theResult = FSpOpenDF(newFileSpec,fsRdWrPerm,&refNum);
  188.     if (refNum != -1)
  189.         {
  190.         if (theResult = SetFPos(refNum,fsFromStart,0))
  191.             return(theResult);
  192.  
  193.         if (theDocument->theTE != NULL)
  194.             {
  195.             long    length;
  196.             char*    bufPtr;
  197.             length = (**(theDocument->theTE)).teLength;
  198.             bufPtr = *((**(theDocument->theTE)).hText);
  199.  
  200.             if (theResult = FSWrite(refNum,&length,bufPtr))
  201.                 return(theResult);
  202.  
  203.             theResult = SetEOF(refNum,length);
  204.             }
  205.         else
  206.             {
  207.             long headerSize = kPictHeaderSize;
  208.             long pictSize = theDocument->fPictLength;
  209.  
  210.             theResult = FSWrite(refNum,&headerSize,*theDocument->fHeader);
  211.             theResult = FSWrite(refNum,&pictSize,*theDocument->fPict);
  212.             
  213.             theResult = SetEOF(refNum,headerSize+pictSize);
  214.             }
  215.         theResult = FSClose(refNum);
  216.         }
  217.     return theResult;
  218. }
  219.  
  220.  
  221. // *****************************************************************************
  222. // *
  223. // *    DoNewDocument()
  224. // *
  225. // *****************************************************************************
  226. void DoNewDocument(Boolean newDocAsPICT)
  227. {    
  228.     Document* theDocument;
  229.     if (theDocument = NewDocument(newDocAsPICT))
  230.         ShowWindow(theDocument->theWindow);
  231. }
  232.  
  233.  
  234. // *****************************************************************************
  235. // *
  236. // *    DoOpenFile()
  237. // *
  238. // *****************************************************************************
  239. OSErr DoOpenFile(FSSpec* theFile, Boolean openAsPICT)
  240. {    
  241.     OSErr        result;
  242.     short        refNum;
  243.     Document*    theDocument = NULL;
  244.  
  245.     result = FSpOpenDF(theFile,fsRdWrPerm,&refNum);
  246.     if ((result == fLckdErr) || (result == afpAccessDenied))
  247.         result = FSpOpenDF(theFile,fsRdPerm,&refNum);
  248.  
  249.     if (result == noErr)
  250.         {
  251.         theDocument = NewDocument(openAsPICT);
  252.         if (theDocument != NULL)
  253.             {
  254.             theDocument->fRefNum = refNum;
  255.             
  256.             result = ReadFile(theDocument);
  257.                 
  258.             SetWTitle(theDocument->theWindow,theFile->name);
  259.             SizeDocWindow(theDocument);
  260.  
  261.             AdjustScrollBar(theDocument);
  262.             ShowWindow(theDocument->theWindow);    
  263.             }
  264.         else
  265.             {
  266.             FSClose(refNum);
  267.             result = memFullErr;
  268.             }
  269.         }
  270.     else
  271.         {
  272.         Str255 errorStr;
  273.         if (result == vLckdErr || result == afpVolLocked || result == wPrErr || result == permErr)
  274.             GetIndString(errorStr,rAppStringsID,sWriteToBusyFileErr);
  275.         else
  276.             if (result == opWrErr)
  277.                 GetIndString(errorStr,rAppStringsID,sBusyOpen);
  278.             else
  279.                 GetIndString(errorStr,rAppStringsID,sOpeningErr);
  280.         ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  281.         NoteAlert(rGenericAlertID,0L);
  282.         }
  283.     return result;
  284. }
  285.  
  286.  
  287. // *****************************************************************************
  288. // *
  289. // *    myFilterProc()
  290. // *
  291. // *    If user choose "none" for 'open' resoure filtering, this routine could
  292. // *    affect the filter if used!
  293. // *
  294. // *****************************************************************************
  295. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData /*callBackUD*/, NavFilterModes /*filterMode*/)
  296. {
  297.     OSErr                     theErr = noErr;
  298.     Boolean                 display = true;
  299.     NavFileOrFolderInfo*    theInfo;
  300.  
  301.     if (theItem->descriptorType == typeFSS)
  302.         {
  303.         theInfo = (NavFileOrFolderInfo*)info;    
  304.         if (((theInfo->isFolder) && (theInfo->visible)) ||
  305.             ((theInfo->fileAndFolder.fileInfo.finderInfo.fdFlags & kIsAlias) != 0))
  306.             display &= true;            // item is a visible folder (normal or aliased)
  307.         else
  308.             switch (theInfo->fileAndFolder.fileInfo.finderInfo.fdType)
  309.                 {
  310.                 case 'TEXT':
  311.                 case 'PICT':
  312.                     display &= true;
  313.                     break;
  314.                 }
  315.         }
  316.     return display;
  317. }
  318.  
  319.  
  320. // *****************************************************************************
  321. // *
  322. // *    myEventProc()    
  323. // *
  324. // *****************************************************************************
  325. pascal void myEventProc(const NavEventCallbackMessage callBackSelector, 
  326.                         NavCBRecPtr callBackParms, 
  327.                         NavCallBackUserData callBackUD)
  328. {
  329.     WindowPtr    pWindow = NULL;
  330.     Document**    docList;
  331.     Document*    theDoc = NULL;
  332.     short         index = 0;
  333.  
  334.     if (callBackUD != 0)
  335.         switch (callBackSelector)
  336.             {
  337.             case kNavCBEvent:
  338.                 {
  339.                 docList = (Document**)callBackUD;
  340.                 if (docList != NULL)
  341.                     switch (callBackParms->eventData.event->what)
  342.                         {
  343.                         case nullEvent:
  344.                             break;
  345.                             
  346.                         case updateEvt:
  347.                             pWindow = (WindowPtr)callBackParms->eventData.event->message;
  348.                             theDoc = docList[index];
  349.                             if (theDoc != NULL)
  350.                                 {
  351.                                 while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  352.                                     {
  353.                                     index++;
  354.                                     theDoc = docList[index];
  355.                                     }
  356.                                 theDoc = docList[index];
  357.                                 if (theDoc != NULL)
  358.                                     UpdateWindow(theDoc);
  359.                                 }
  360.                             break;
  361.  
  362.                         case activateEvt:
  363.                             break;
  364.  
  365.                         default:
  366.                             break;
  367.                         }
  368.                 break;
  369.                 }
  370.             }
  371. }
  372.  
  373.  
  374. // *****************************************************************************
  375. // *
  376. // *    DoOpenDocumentTheOldWay()
  377. // *
  378. // *****************************************************************************
  379. OSErr DoOpenDocumentTheOldWay()
  380. {    
  381.     OSErr theErr = noErr;
  382.     SFTypeList            theTypeList;
  383.     StandardFileReply    theReply;
  384.  
  385.     theTypeList[0] = 'TEXT';
  386.     theTypeList[1] = 'PICT';
  387.     StandardGetFile(0L,2,theTypeList,&theReply);
  388.  
  389.     if (theReply.sfGood)
  390.         {
  391.         if (theReply.sfType == 'TEXT')
  392.             DoOpenFile(&theReply.sfFile,false);
  393.         else
  394.             DoOpenFile(&theReply.sfFile,true);
  395.         }
  396.     return theErr;
  397. }
  398.  
  399.  
  400. // *****************************************************************************
  401. // *
  402. // *    DoOpenDocument()
  403. // *
  404. // *****************************************************************************
  405. OSErr DoOpenDocument()
  406. {    
  407.     NavReplyRecord        theReply;
  408.     NavDialogOptions    dialogOptions;
  409.     OSErr                theErr = noErr;
  410.     NavTypeListHandle    openList = NULL;
  411.     long                count = 0;
  412.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  413.     NavObjectFilterUPP    filterUPP = NewNavObjectFilterProc(myFilterProc);
  414.     
  415.     // default behavior for browser and dialog:
  416.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  417.  
  418.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  419.     
  420.     openList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID);
  421.     if ((openList != NULL)&&(ResError() == noErr))
  422.         HLock((Handle)openList);
  423.  
  424.     dialogOptions.preferenceKey = kOpenPrefKey;
  425.  
  426.     dialogOptions.dialogOptionFlags += kDontAutoTranslate;    // we will do the translation ourselves later:
  427.  
  428.     theErr = NavGetFile(NULL,    // use system's default location
  429.                         &theReply,
  430.                         &dialogOptions,
  431.                         eventUPP,
  432.                         NULL,    // no custom previews
  433.                         filterUPP,
  434.                         (NavTypeListHandle)openList,
  435.                         (NavCallBackUserData)&gDocumentList);
  436.  
  437.     DisposeRoutineDescriptor(eventUPP);
  438.     DisposeRoutineDescriptor(filterUPP);
  439.  
  440.     if (theReply.validRecord && theErr == noErr)
  441.         {
  442.         // since we allow for multiple objects to be returned,
  443.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  444.         FSSpec    finalFSSpec;    
  445.         AEDesc     resultDesc;
  446.         FInfo    fileInfo;
  447.  
  448.         // in the case we didn't want built in translation:
  449.         if ((dialogOptions.dialogOptionFlags & kDontAutoTranslate) != 0)
  450.             if (theReply.translationNeeded)
  451.                 {
  452.                 // if we didn't want built in translation it was for the following reasons:
  453.                 //        1) we wanted to do it ourselves
  454.                 //        2) or we wanted to defer it    
  455.                 // things to remember if auto-translation is turned off:
  456.                 //         1) the AEDesc list contains the original file specs the user had chosen.
  457.                 //        2) the 'fileTranslation' field for each object that needs translation has filled in for you.
  458.                 
  459.                 // put your own code here to perform your own translation.
  460.                 // - or -
  461.                 // we can simply call this to perform the translation manually:
  462.                 Str255     errorStr;
  463.  
  464.                 if ((theErr = NavTranslateFile(&theReply,kNavTranslateCopy)) != noErr)
  465.                     {
  466.                     if (theErr == vLckdErr || theErr == afpVolLocked || theErr == wPrErr || theErr == permErr)
  467.                         GetIndString(errorStr,rAppStringsID,sTranslationLockedErr);
  468.                     else
  469.                         GetIndString(errorStr,rAppStringsID,sTranslationErr);
  470.                     ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  471.                     NoteAlert(rGenericAlertID,0L);
  472.                     }
  473.                 }
  474.  
  475.         if (theErr == noErr)
  476.             {
  477.             // we are ready to open the document(s), grab information about each file for opening:
  478.             theErr = AECountItems(&(theReply.selection),&count);
  479.             for (long index=1;index<=count;index++)
  480.                 {
  481.                 resultDesc.dataHandle = 0L;
  482.                 theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc);
  483.                 if (theErr == noErr)
  484.                     {
  485.                     BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  486.                 
  487.                     // decide if the doc we are opening is a 'PICT' or 'TEXT':
  488.                     theErr = FSpGetFInfo(&finalFSSpec,&fileInfo);
  489.                     if (theErr == noErr)
  490.                         {
  491.                         if (fileInfo.fdType == kFileType)
  492.                             (void)DoOpenFile(&finalFSSpec,false);
  493.                         else
  494.                             if (fileInfo.fdType == kFileTypePICT)
  495.                                 (void)DoOpenFile(&finalFSSpec,true);
  496.                             else
  497.                                 {
  498.                                 // error:
  499.                                 // if we got this far, the document is a type we can't open and
  500.                                 // (most likely) built-in translation was turned off.
  501.                                 // You can alert the user that this returned selection or file spec
  502.                                 // needs translation.
  503.                                 }
  504.                         }
  505.                     theErr = AEDisposeDesc(&resultDesc);
  506.                     }
  507.                 }
  508.             }
  509.         
  510.         theErr = NavDisposeReply(&theReply);    // clean up after ourselves    
  511.         }
  512.  
  513.     if (openList != NULL)
  514.         {
  515.         HUnlock((Handle)openList);
  516.         ReleaseResource((Handle)openList);
  517.         }
  518.  
  519.     return theErr;
  520. }
  521.  
  522.  
  523. // *****************************************************************************
  524. // *
  525. // *    SaveACopyDocumentTheOldWay()
  526. // *
  527. // *****************************************************************************
  528. OSErr SaveACopyDocumentTheOldWay(Document* theDocument)
  529. {
  530.     OSErr                theErr = noErr;
  531.     Str255                thePrompt, theName;
  532.     StandardFileReply    theReply;
  533.  
  534.     if (!theDocument)
  535.         return false;
  536.  
  537.     GetIndString((unsigned char*)&thePrompt,rAppStringsID,sSaveCopyMessage);
  538.     GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  539.     StandardPutFile((unsigned char*)&thePrompt,(unsigned char*)&theName,&theReply);
  540.  
  541.     if (theReply.sfGood)
  542.         {
  543.         if (theReply.sfReplacing)
  544.             theErr = FSpDelete(&theReply.sfFile);
  545.  
  546.         if ((theErr = FSpCreate(&theReply.sfFile,kFileCreator,'TEXT',smSystemScript)) == noErr)
  547.             theErr = WriteNewFile(theDocument,&theReply.sfFile);    // use this document's data to write to our new copy:
  548.         
  549.         if (theErr == fBsyErr)
  550.             {
  551.             Str255 errorStr;
  552.             GetIndString(errorStr,rAppStringsID,sWriteToBusyFileErr);
  553.             ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  554.             NoteAlert(rGenericAlertID,0L);
  555.             }
  556.         }
  557.     else
  558.         return false;
  559.         
  560.     return true;
  561. }
  562.  
  563.  
  564. // *****************************************************************************
  565. // *
  566. // *    SaveACopyDocument()
  567. // *
  568. // *****************************************************************************
  569. OSErr SaveACopyDocument(Document* theDocument)
  570. {    
  571.     OSErr                theErr = noErr;
  572.     NavReplyRecord        theReply;
  573.     NavDialogOptions    dialogOptions;
  574.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  575.     Str255                docTitle;
  576.     OSType                fileTypeToSave;
  577.  
  578.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  579.     
  580.     // default behavior for browser and dialog:
  581.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  582.  
  583.     GetWTitle(theDocument->theWindow,docTitle);
  584.     p2cstr((StringPtr)docTitle);
  585.     sprintf((char*)dialogOptions.savedFileName,(char*)"%s copy",docTitle);
  586.     c2pstr((Ptr)dialogOptions.savedFileName);
  587.         
  588.     if (theDocument->theTE != NULL)    // which document type is it?
  589.         fileTypeToSave = kFileType;
  590.     else
  591.         fileTypeToSave = kFileTypePICT;
  592.  
  593.     dialogOptions.preferenceKey = kSavePrefKey;
  594.  
  595.     theErr = NavPutFile(NULL,    // use system's default location
  596.                         &theReply,
  597.                         &dialogOptions,
  598.                         eventUPP,
  599.                         fileTypeToSave,
  600.                         kFileCreator,
  601.                         (NavCallBackUserData)&gDocumentList);
  602.  
  603.     DisposeRoutineDescriptor(eventUPP);
  604.  
  605.     if ((theReply.validRecord)&&(theErr == noErr))
  606.         {
  607.         FSSpec    finalFSSpec;    
  608.         AEDesc     resultDesc;    
  609.         resultDesc.dataHandle = 0L;
  610.         
  611.         // retrieve the returned selection:
  612.         // since only 1 selection is possible, we get the first AEDesc:
  613.         theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc);
  614.         if (theErr == noErr)
  615.             {
  616.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  617.  
  618.             if (theReply.replacing)
  619.                 theErr = FSpDelete(&finalFSSpec);
  620.             if (theErr == noErr)
  621.                 {
  622.                 theErr = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,smSystemScript);
  623.                 if (theErr == noErr)
  624.                     {
  625.                     theErr = WriteNewFile(theDocument,&finalFSSpec);    // use this document's data to write to our new copy
  626.                     if (theErr == noErr)
  627.                         {
  628.                         // translation may be needed for file we are saving a copy of,
  629.                         // when you save a copy, you should always "translate in place":
  630.                         theErr = NavCompleteSave(&theReply,kNavTranslateInPlace);
  631.                         }
  632.                     }
  633.                 }
  634.             else
  635.                 if (theErr == fBsyErr)
  636.                     {
  637.                     Str255 errorStr;
  638.                     GetIndString(errorStr,rAppStringsID,sReadErr);
  639.                     ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  640.                     NoteAlert(rGenericAlertID,0L);
  641.                     }
  642.             }
  643.         theErr = NavDisposeReply(&theReply);
  644.         }
  645.     
  646.     return theErr;
  647. }
  648.  
  649.  
  650. // *****************************************************************************
  651. // *
  652. // *    DoSaveAsDocument()
  653. // *
  654. // *****************************************************************************
  655. short DoSaveAsDocument(Document* theDocument)
  656. {
  657.     OSErr                theErr = noErr;
  658.     short                result = true;
  659.     NavReplyRecord        theReply;
  660.     NavDialogOptions    dialogOptions;
  661.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  662.     OSType                fileTypeToSave;
  663.  
  664.     // default behavior for browser and dialog:
  665.     NavGetDefaultDialogOptions(&dialogOptions);
  666.  
  667.     GetWTitle(theDocument->theWindow,dialogOptions.savedFileName);
  668.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  669.             
  670.     if (theDocument->theTE != NULL)    // which document type is it?
  671.         fileTypeToSave = kFileType;
  672.     else
  673.         fileTypeToSave = kFileTypePICT;
  674.  
  675.     dialogOptions.preferenceKey = kSavePrefKey;
  676.  
  677.     theErr = NavPutFile(NULL,    // use system's default location
  678.                         &theReply,
  679.                         &dialogOptions,
  680.                         eventUPP,
  681.                         fileTypeToSave,
  682.                         kFileCreator,
  683.                         (NavCallBackUserData)&gDocumentList);
  684.     DisposeRoutineDescriptor(eventUPP);
  685.  
  686.     if (theReply.validRecord && theErr == noErr)
  687.         {
  688.         FSSpec    finalFSSpec;    
  689.         AEDesc     resultDesc;    
  690.         resultDesc.dataHandle = 0L;
  691.         
  692.         // retrieve the returned selection:
  693.         theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc);
  694.         if (theErr == noErr)
  695.             {
  696.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  697.  
  698.             if (!theReply.replacing)
  699.                 {
  700.                 result = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,theReply.keyScript);
  701.                 if (result)
  702.                     {
  703.                     SysBeep(5);
  704.                     return false;
  705.                     }
  706.                 }
  707.                 
  708.             if (theDocument->fRefNum)
  709.                 result = FSClose(theDocument->fRefNum);
  710.             
  711.             result = FSpOpenDF(&finalFSSpec,fsRdWrPerm,&theDocument->fRefNum);
  712.             if (result)
  713.                 {
  714.                 SysBeep(5);
  715.                 return false;
  716.                 }
  717.  
  718.             if (result = WriteFile(theDocument))
  719.                 {
  720.                 SysBeep(5);
  721.                 return false;
  722.                 }
  723.  
  724.             SetWTitle(theDocument->theWindow,(unsigned char*)finalFSSpec.name);
  725.             theDocument->dirty = false;
  726.             }
  727.  
  728.         NavDisposeReply(&theReply);
  729.         }
  730.     else
  731.         return false;
  732.  
  733.     return result;
  734. }
  735.  
  736.  
  737. // *****************************************************************************
  738. // *
  739. // *    DoSaveAsDocumentOldWay()
  740. // *
  741. // *****************************************************************************
  742. short DoSaveAsDocumentOldWay(Document* theDocument)
  743. {    
  744.     short                theResult;
  745.     Str255                thePrompt, theName;
  746.     StandardFileReply    theReply;
  747.     OSType                fileTypeToSave;
  748.  
  749.     if (!theDocument)
  750.         return false;
  751.  
  752.     GetIndString((unsigned char*)&thePrompt,rAppStringsID,slSavePromptIndex);
  753.     GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  754.     StandardPutFile((unsigned char*)&thePrompt,(unsigned char*)&theName,&theReply);
  755.  
  756.     if (theDocument->theTE != NULL)    // which document type is it?
  757.         fileTypeToSave = kFileType;
  758.     else
  759.         fileTypeToSave = kFileTypePICT;
  760.  
  761.     if (theReply.sfGood)
  762.         {
  763.         if (!theReply.sfReplacing)
  764.             {
  765.             theResult = FSpCreate(&theReply.sfFile,kFileCreator,fileTypeToSave,theReply.sfScript);
  766.             if (theResult)
  767.                 {
  768.                 SysBeep(5);
  769.                 return false;
  770.                 }
  771.             }
  772.             
  773.         if (theDocument->fRefNum)
  774.             theResult = FSClose(theDocument->fRefNum);
  775.         
  776.         theResult = FSpOpenDF(&theReply.sfFile,fsRdWrPerm,&theDocument->fRefNum);
  777.         if (theResult)
  778.             {
  779.             SysBeep(5);
  780.             return false;
  781.             }
  782.  
  783.         if (theResult = WriteFile(theDocument))
  784.             {
  785.             SysBeep(5);
  786.             return false;
  787.             }
  788.  
  789.         SetWTitle(theDocument->theWindow,(unsigned char*)theReply.sfFile.name);
  790.         theDocument->dirty = false;
  791.         }
  792.     else
  793.         return false;
  794.         
  795.     return true;
  796. }
  797.  
  798.  
  799. // *****************************************************************************
  800. // *
  801. // *    DoSaveDocument()
  802. // *
  803. // *****************************************************************************
  804. short DoSaveDocument(Document* theDocument)
  805. {
  806.     short result = noErr;
  807.     if (theDocument != NULL)
  808.         {
  809.         if (theDocument->fRefNum)
  810.             {
  811.             if (WriteFile(theDocument))
  812.                 {
  813.                 SysBeep(5);
  814.                 return false;
  815.                 }
  816.             else
  817.                 theDocument->dirty = false;
  818.             result = true;
  819.             }
  820.         else
  821.             {
  822.             // need to save file for the first time:
  823.             if (gNavServicesExists)
  824.                 {
  825.                 result = DoSaveAsDocument(theDocument);
  826.                 }
  827.             else
  828.                 result = DoSaveAsDocumentOldWay(theDocument);    
  829.             }
  830.         }
  831.     return result;
  832. }
  833.  
  834.  
  835. // *****************************************************************************
  836. // *
  837. // *    DoRevertDocument()
  838. // *
  839. // *****************************************************************************
  840. void DoRevertDocument(Document* theDocument)
  841. {    
  842.     if (theDocument != NULL)
  843.     if (theDocument->fRefNum)
  844.         {
  845.         OSErr                         theErr = noErr;
  846.         NavEventUPP                    eventUPP = NewNavEventProc(myEventProc);
  847.         NavAskDiscardChangesResult     reply;
  848.         NavDialogOptions            dialogOptions;
  849.  
  850.         GetWTitle(theDocument->theWindow,dialogOptions.savedFileName);
  851.         theErr = NavAskDiscardChanges(    &dialogOptions,
  852.                                         &reply,
  853.                                         eventUPP,
  854.                                         (NavCallBackUserData)&gDocumentList);
  855.         DisposeRoutineDescriptor(eventUPP);
  856.  
  857.         switch (reply)
  858.             {
  859.             case askDiscardChanges:        
  860.                 if (ReadFile(theDocument))
  861.                     SysBeep(5);
  862.                 break;
  863.  
  864.             case askDiscardChangesCancel:
  865.                 break;
  866.             }
  867.         }
  868. }
  869.  
  870.  
  871. // *****************************************************************************
  872. // *
  873. // *    DoRevertDocumentTheOldWay()
  874. // *
  875. // *****************************************************************************
  876. void DoRevertDocumentTheOldWay(Document* theDocument)
  877. {    
  878.     Str255 theName;
  879.  
  880.     if (!theDocument)
  881.         return;
  882.  
  883.     if (theDocument->fRefNum)
  884.         {
  885.         GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  886.         ParamText((ConstStr255Param)&theName,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  887.         if (Alert(rRevertID,0L) == 1)
  888.             if (ReadFile(theDocument))
  889.                 SysBeep(5);
  890.         }
  891. }
  892.